package com.gitee.wsl.doc.prosemirror.state.command.block.list

import com.gitee.wsl.doc.prosemirror.model.fragment.Fragment
import com.gitee.wsl.doc.prosemirror.model.fragment.Slice
import com.gitee.wsl.doc.prosemirror.model.node.NodeBase
import com.gitee.wsl.doc.prosemirror.model.node.NodeType
import com.gitee.wsl.doc.prosemirror.model.node.ext.canSplit
import com.gitee.wsl.doc.prosemirror.state.Command
import com.gitee.wsl.doc.prosemirror.state.CommandDispatch
import com.gitee.wsl.doc.prosemirror.state.EditorState
import com.gitee.wsl.doc.prosemirror.state.selection.NodeSelection
import com.gitee.wsl.doc.prosemirror.state.selection.Selection
import com.gitee.wsl.doc.prosemirror.transform.ext.delete
import com.gitee.wsl.doc.prosemirror.transform.ext.replace
import com.gitee.wsl.doc.prosemirror.transform.ext.split
import com.gitee.wsl.ext.base.ifValue

class SplitListItem(val itemType: NodeType): Command {

    override fun exec(
        state: EditorState,
        dispatch: CommandDispatch?,
    ): Boolean {
        val selection = state.selection

        if(selection !is NodeSelection) return false

        val from = selection._from
        val to = selection._to
        val node = selection.node

        // 检查选择是否有效
        if (node.isBlock == true || from.depth < 2 || !from.sameParent(to)) {
            return false
        }

        val grandParent = from.node(-1)
        if (grandParent.type != itemType) {
            return false
        }

        // 处理空列表项的情况
        if (from.parent.content.size == 0) {
            if (from.depth == 2 || from.node(-3).type != itemType ||
                from.index(-2) != from.node(-2).childCount.minus(1)) {
                return false
            }

            if (dispatch != null) {
                var wrap = Fragment.empty
                val keepItem = from.index(-1) > 0

                // 构建包含从外层列表项到光标父节点结构的片段
                for (d in from.depth - (if (keepItem) 1 else 2) downTo from.depth - 3) {
                    val node = from.node(d)
                    wrap = Fragment.from(node.copy(wrap))
                }

                // 添加一个带有空默认起始节点的第二个列表项
                val node = itemType.createAndFill()
                wrap = wrap.append(
                    (node!=null).ifValue(Fragment.from(node), Fragment.empty)
                )

                val startPos = from.before(if (keepItem) null else -1)
                val endPos = from.after(-3)
                val slice = Slice(wrap, if (keepItem) 3 else 2, 2)

                val tr = state.tr.replace(startPos, endPos, slice)
                val newPos = from.pos + (if (keepItem) 3 else 2)
                tr.setSelection(Selection.near(tr.doc.resolve(newPos)))
                dispatch(tr.scrollIntoView())
            }
            return true
        }

        // 处理非空列表项的情况
        val nextType = if (to.pos == from.end()) {
            grandParent.contentMatchAt(from.indexAfter(-1)).defaultType
        } else {
            null
        }

        val tr = state.tr.delete(from.pos, to.pos)
        val types = nextType?.let { listOf(NodeBase(it)) }

        if (!tr.doc.canSplit( from.pos, 2, types)) {
            return false
        }

        if (dispatch != null) {
            val splitTr = tr.split(from.pos, 2, types)
            dispatch(splitTr.scrollIntoView())
        }
        return true
    }
}

// :: (NodeType) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool
// build a command that splits a non-empty textblock at the top level
// of a list item by also splitting that list item.
fun Command.Companion.splitListItem(itemType: NodeType) = SplitListItem( itemType)